/***************************************************
*	(c) Tody 2012, T-ware Inc.
*
*	Free software under GPLv3
*
*	Function: get DRM* widevine keybox data from MIS ShopFloor
*	FileName: miswvkey.c
*	Author: Tody Guo
*
* changelog:
*	v1.0.0 @ 2014-10-19
*	*) first release...
****************************************************/

#include "stdafx.h"
#include "soapH.h"
#include "ServiceSoap.nsmap"
#include <stdio.h>

#define progname	"mis"
#define	version		"1.0.3"
#define DEBUG				1

typedef struct _wvbox
{
	char DeviceId[32];
	char Key[16];
	char ID[72];
	char Magic[4];
	char CRC[4];
}WVBOX;

typedef struct uniqData
{
	char SN[256];
	char UUID[256];
	char LANMAC[256];
	char WIFIMAC[256];
	char BTMAC[256];
	char OAKEY[256];
	char IMEI[256];
	char WVBOX[256];
	/* Add more mes data */
	 char SITE[256];
	 char WO[256];
	 char BIOS[256];
	 char CPUID[256];
	 char SYSFLAG[256];
	 char TDINDEX[256];
	 char SHIPIMAGE[256];
	 char WORKERID[256];
	 char HDDSN[256];
}UNIQDATA;

void usage(void)
{
	fprintf(stderr, "Recieve MES data from Shopfloor tool   Version: %s\n"
		"\n(c) Tody 2014, T-ware Inc.\n"
		"\nUsage:\t%s -url http://172.20.160.1:888/Service.asmx [-g <Serialnumber> <customer-id>] [-c <File>] [-auto-station <File>]"
		"\nOptions:\n"
		"      -url <website>       website must be assigned\n"
		"      -g                   get key from MES\n"
		"      customer-id          specified customer id to get keys\n"
		"      Serialnumber         get Data from shopfloor via Tablet Serial number\n"
		"      Device ID            specified Device ID to shopfloor that was consumed\n"
		"      -c File              specified formated file to check data with MES\n"
		"      -auto-station File   specified formated file to pass station to MES\n", version, progname);
	exit(1);
}

int getValueFromIni(char* inifile, UNIQDATA* data)
{
	GetPrivateProfileStringA("MESDATA", "SN", "NA", data->SN, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "UUID", "NA", data->UUID, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "LANMAC", "NA", data->LANMAC, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "WIFIMAC", "NA", data->WIFIMAC, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "BTMAC", "NA", data->BTMAC, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "OAKEY", "NA", data->OAKEY, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "IMEI", "NA", data->IMEI, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "WVBOX", "NA", data->WVBOX, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "SITE", "NA", data->SITE, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "WO", "NA", data->WO, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "BIOS", "NA", data->BIOS, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "CPUID", "NA", data->CPUID, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "SYSFLAG", "NA", data->SYSFLAG, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "TDINDEX", "NA", data->TDINDEX, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "SHIPIMAGE", "NA", data->SHIPIMAGE, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "WORKERID", "NA", data->WORKERID, 256, inifile);
	GetPrivateProfileStringA("MESDATA", "HDDSN", "NA", data->HDDSN, 256, inifile);
}

int charToHex(char ch)
{
	switch (ch) {
	case '0':	return 0; break;
	case '1':	return 1; break;
	case '2':	return 2; break;
	case '3':	return 3; break;
	case '4':	return 4; break;
	case '5':	return 5; break;
	case '6':	return 6; break;
	case '7':	return 7; break;
	case '8':	return 8; break;
	case '9':	return 9; break;
	case 'a':
	case 'A': return 10; break;
	case 'b':
	case 'B':	return 11; break;
	case 'c':
	case 'C':	return 12; break;
	case 'd':
	case 'D':	return 13; break;
	case 'e':
	case 'E':	return 14; break;
	case 'f':
	case 'F':	return 15; break;
	default:
		printf("char error\n");
		exit(1);
	}
}

int dumpToBin(char* filename, WVBOX* wvbox)
{
	FILE* f;
	f = fopen(filename, "wb");
	fwrite(wvbox, sizeof(WVBOX), 1, f);
	fflush(f);
	fclose(f);
}

int doDataSplit(char* data, char* serialNumber)
{
	char* father;
	char buf[1024];
	WVBOX wvbox;
	int i = 0, j = 0;
	int index = 1;
	char filename[128];

	/* generate filename of BIN. according serial number */
	sprintf(filename, "%s.BIN", serialNumber);

	memset(buf, 0, sizeof(buf));
	memset(&wvbox, 0, sizeof(WVBOX));

	strcpy(buf, data);

	printf("\nDecode MES Data...");
	father = strtok(buf, "|");
	while (father != NULL)
	{
		switch (index) {
		case 1: /* DeviceID */
			strcpy(wvbox.DeviceId, father);
			printf("\nDevice ID:%s", wvbox.DeviceId);
			break;
		case 2: /* Key */
			printf("\nKey: %s", father);
			if (strlen(father) != 32) {
				printf("\n[-] Key length error");
				exit(1);
			}
			for (i = 0, j = 0; i < 32; i = i + 2) {
				wvbox.Key[j] = charToHex(father[i]) * 16 + charToHex(father[i + 1]);
				j++;
			}
			break;
		case 3:/* ID */
			printf("\nID: %s", father);
			if (strlen(father) != 144) {
				printf("\n[-] ID length error");
				exit(1);
			}
			for (i = 0, j = 0; i < 144; i = i + 2) {
				wvbox.ID[j] = charToHex(father[i]) * 16 + charToHex(father[i + 1]);
				j++;
			}
			break;
		case 4:/* Magic */
			printf("\nMagic: %s", father);
			if (strlen(father) != 8) {
				printf("\n[-] Magic length error");
				exit(1);
			}
			for (i = 0, j = 0; i < 8; i = i + 2) {
				wvbox.Magic[j] = charToHex(father[i]) * 16 + charToHex(father[i + 1]);
				j++;
			}
			break;
		case 5: /* CRC */
			printf("\nCRC: %s", father);
			if (strlen(father) != 8) {
				printf("\n[-] CRC length error");
				exit(1);
			}
			for (i = 0, j = 0; i < 8; i = i + 2) {
				wvbox.CRC[j] = charToHex(father[i]) * 16 + charToHex(father[i + 1]);
				j++;
			}
			break;
		}
		father = strtok(NULL, "|");
		index++;
	}

	if ((index - 1) != 5) {
		printf("\n[-]Keybox format error!");
		exit(1);
	}

	dumpToBin(filename, &wvbox);
}


int main(int argc, char* argv[])
{
	struct soap* soap;
	struct _ns1__FetchKeystr 		sn;
	struct _ns1__FetchKeystrResponse 	retData;

	struct _ns1__Check_USCOREUnique uniq;
	struct _ns1__Check_USCOREUniqueResponse uniqRes;
	UNIQDATA uData;

	struct _ns1__SN_USCOREAutoProcess autoProc;
	struct _ns1__SN_USCOREAutoProcessResponse autoProcRes;

	char MISDATA[512];   /*Size is ok for later use?*/
	char* website = NULL;

	memset(MISDATA, 0, sizeof(MISDATA));

	if (argc >= 3 && strcmp("-url", argv[1]) != 0)
	{
		usage();
	}
	else if (argc >= 3 && strstr(argv[2], "http://") != NULL)
	{
		website = argv[2];
	}
	else {
		/*using default website.*/
		website = NULL;
	}

	printf("Accessing %s...\n", website == NULL ? "Default website" : website);

	soap = soap_new();

	if (argc == 6 && strcmp("-g", argv[3]) == 0)
	{
		sn.sn = argv[4];
		sn.customer = argv[5];
		retData.FetchKeystrResult = MISDATA;

		if (soap_call___ns1__FetchKeystr(soap, website, NULL, &sn, &retData) == SOAP_OK)
		{
			if (strlen(retData.FetchKeystrResult) != 0)
			{
				fprintf(stdout, "\n-------------------------------------------------------------------------------");
				fprintf(stdout, "\nMIS: %s", retData.FetchKeystrResult);
				fprintf(stdout, "\n-------------------------------------------------------------------------------");
				doDataSplit(retData.FetchKeystrResult, argv[4]);
				fflush(stdout);
			}
			else {
				soap_end(soap);
				free(soap);
				printf(" -> data not found!");
				exit(1);
			}
		}
		else
		{
			soap_end(soap);
			free(soap);
			fprintf(stdout, "[-] network issue!");
			exit(1);
		}
	}
	else if (argc == 5 && strcmp("-c", argv[3]) == 0)
	{
		memset(&uData, 0, sizeof(UNIQDATA));

		getValueFromIni(argv[4], &uData);

		uniq.TSN = uData.SN;
		uniq.TUUID = uData.UUID;
		uniq.TLANMAC = uData.LANMAC;
		uniq.TWIFIMAC = uData.WIFIMAC;
		uniq.TBTMAC = uData.BTMAC;
		uniq.TOAKEY = uData.OAKEY;
		uniq.TIMEI = uData.IMEI;
		uniq.TWVBOX = uData.WVBOX;
		uniq.THDD = uData.HDDSN;
		uniq.TERIMINALID = uData.SITE;

		printf("\nCheck-process...\nTSN: %s\nTUUID: %s\nTLANMAC: %s\nTWIFIMAC: %s\nTBTMAC: %s\nTOAKEY: %s\nTIMEI: %s\nTWVBOX: %s\nTHDD: %s\n",
			uniq.TSN, uniq.TUUID, uniq.TLANMAC, uniq.TWIFIMAC, uniq.TBTMAC, uniq.TOAKEY, uniq.TIMEI, uniq.TWVBOX, uniq.THDD);

		if (soap_call___ns1__Check_USCOREUnique(soap, website, NULL, &uniq, &uniqRes) == SOAP_OK) {
			fprintf(stdout, "\nMES:%s", uniqRes.Check_USCOREUniqueResult);
			fflush(stdout);
		}
		else
		{
			fprintf(stdout, "[-] network issue!");
			soap_end(soap);
			free(soap);
			exit(1);
		}

	}
	else if (argc == 5 && strcmp("-auto-station", argv[3]) == 0)
	{
		memset(&uData, 0, sizeof(UNIQDATA));

		getValueFromIni(argv[4], &uData);

		autoProc.TSN = (char *)uData.SN;
		autoProc.TUUID = uData.UUID;
		autoProc.TLANMAC = uData.LANMAC;
		autoProc.TWIFIMAC = uData.WIFIMAC;
		autoProc.TBTMAC = uData.BTMAC;
		autoProc.TOAKEY = uData.OAKEY;
		autoProc.TIMEI = uData.IMEI;
		autoProc.TWVBOX = uData.WVBOX;
		autoProc.TSITEY = uData.SITE;
		autoProc.TWO = uData.WO;
		autoProc.TBIOS = uData.BIOS;
		autoProc.TCPUID = uData.CPUID;
		autoProc.TSYSFLAG = uData.SYSFLAG;
		autoProc.TDINDEX = uData.TDINDEX;
		autoProc.TSHIPIMAGE = uData.SHIPIMAGE;
		autoProc.TEMP = uData.WORKERID;

		printf("\nAuto-process...\nTSN: %s\nTUUID: %s\nTLANMAC: %s\nTWIFIMAC: %s\nTBTMAC: %s\nTOAKEY: %s\nTIMEI: %s\nTWVBOX: %s\n",
			autoProc.TSN, autoProc.TUUID, autoProc.TLANMAC, autoProc.TWIFIMAC, autoProc.TBTMAC, autoProc.TOAKEY, autoProc.TIMEI, autoProc.TWVBOX);
		if (soap_call___ns1__SN_USCOREAutoProcess_(soap, website, NULL, &autoProc, &autoProcRes) == SOAP_OK) {
			fprintf(stdout, "\nMES:%s", autoProcRes.SN_USCOREAutoProcessResult);
			fflush(stdout);
		}
		else
		{
			fprintf(stdout, "[-] network issue!");
			soap_end(soap);
			free(soap);
			exit(1);
		}
	}
	else {
		usage();
	}

	soap_end(soap);
	free(soap);

	exit(0);  /*normal exit from program*/
}

